package com.opener.common.code.assistant.gen;

import com.opener.common.code.assistant.model.Prop;
import com.opener.common.code.assistant.model.Tab;
import org.springframework.util.StringUtils;

import java.util.SortedSet;
import java.util.TreeSet;

public class ControllerGenerator extends DaoGenerator{

    public ControllerGenerator(Ctx ctx, Ctx.MvcClass mvcClass) {
        super(ctx, mvcClass);
    }

    private String createGetDoc(String methodName){
        Tab tab = getMvcClass().getTab();
        StringBuffer s = new StringBuffer();
        s.append("\t/**\n");
        s.append("\t *\n");
        s.append("\t * @api {GET} /api/v1/"+getMvcClass().getModName()+"/"+methodName+"\n");
        s.append("\t * @apiGroup "+tab.getTable()+"\n");
        s.append("\t * @apiDescription\n");
        s.append("\t *\n");
        s.append("\t * @apiSuccessExample {json} 返回示例:\n");
        s.append("\t * {\n");
        s.append("\t *\t\"status\":0,\n");
        s.append("\t *\t\"msg\":\"操作成功\"\n");
        s.append("\t * }\n");
        s.append("\t */");

        return s.toString();
    }
    private String createAddFuncDoc(String methodName){
        Tab tab = getMvcClass().getTab();
        StringBuffer s = new StringBuffer();
        s.append("\t/**\n");
        s.append("\t *\n");
        s.append("\t * @api {POST} /api/v1/"+getMvcClass().getModName()+"/"+methodName+"\n");
        s.append("\t * @apiGroup "+tab.getTable()+"\n");
        s.append("\t * @apiDescription\n");
        s.append("\t * @apiHeader {String} content-type application/json\n");
        s.append("\t *\n");
        for (int i = 0, n = tab.getProps().size();i<n;i++){
            Prop prop = tab.getProps().get(i);
            String comment = "";
            if (prop.getComment() != null){
                comment = prop.getComment();
            }
            s.append("\t * @apiParam {"+prop.getJavaType()+"} "+prop.getJavaProp() +" "+comment+"\n");
        }
        s.append("\t * @apiParamExample {json} 参数示例:\n");
        s.append("\t * @apiSuccessExample {json} 返回示例:\n");
        s.append("\t * {\n");
        s.append("\t *     \"status\":0,\n");
        s.append("\t *     \"msg\":\"操作成功\"\n");
        s.append("\t * }\n");
        s.append("\t */");

        return s.toString();
    }
    @Override
    public String createInsertFunc(){
        Ctx.MvcClass modelCls = getCtx().getMvcClass("model");
        Ctx.MvcClass serviceCls = getCtx().getMvcClass("service");
        String doc = createAddFuncDoc("add");
        String funcBody = doc+
                "\n\t@RequestMapping(value = \"/add\", method = RequestMethod.POST)\n"+
                "\tpublic HttpResponse add(@RequestBody "+modelCls.getClassName()+" "+Utils.lowerFistAlpha(modelCls.getClassName())+", BindingResult br){\n"+
                "\t\tif (br.hasErrors()){\n" +
                "\t\t\tthrow new ArgumentsException(br.getFieldError().getDefaultMessage());\n" +
                "\t\t}\n"+
                "\t\tInteger id = "+Utils.lowerFistAlpha(serviceCls.getClassName())+".add("+Utils.lowerFistAlpha(modelCls.getClassName())+");\n"+
                "\t\tHttpResponse ret = null;\n"+
                "\t\tif(id == null){\n"+
                "\t\t\tret = HttpResponse.getFailureResponse();\n"+
                "\t\t\treturn ret;\n"+
                "\t\t}\n"+
                "\t\tret = HttpResponse.getSuccessResponse();\n"+
                "\t\tret.setData("+Utils.lowerFistAlpha(modelCls.getClassName())+".getId());\n"+
                "\t\treturn ret;\n"+
                "\t}\n";
        return funcBody;
    }
    @Override
    public String createUpdateFunc(){
        Ctx.MvcClass modelCls = getCtx().getMvcClass("model");
        Ctx.MvcClass serviceCls = getCtx().getMvcClass("service");
        String doc = createAddFuncDoc("update");
        String funcBody = doc+
                "\n\t@RequestMapping(value = \"/update\", method = RequestMethod.POST)\n"+
                "\tpublic HttpResponse update(@RequestBody "+modelCls.getClassName()+" "+Utils.lowerFistAlpha(modelCls.getClassName())+", BindingResult br){\n"+
                "\t\tboolean flag = "+Utils.lowerFistAlpha(serviceCls.getClassName())+".update("+Utils.lowerFistAlpha(modelCls.getClassName())+");\n"+
                "\t\tif (br.hasErrors()){\n" +
                "\t\t\tthrow new ArgumentsException(br.getFieldError().getDefaultMessage());\n" +
                "\t\t}\n"+
                "\t\tHttpResponse ret = null;\n"+
                "\t\tif(!flag){\n"+
                "\t\t\tret = HttpResponse.getFailureResponse();\n"+
                "\t\t\treturn ret;\n"+
                "\t\t}\n"+
                "\t\tret = HttpResponse.getSuccessResponse();\n"+
                "\t\treturn ret;\n"+
                "\t}\n";
        return funcBody;
    }
    @Override
    public String createGetFunc(){
        Ctx.MvcClass modelCls = getCtx().getMvcClass("model");
        Ctx.MvcClass serviceCls = getCtx().getMvcClass("service");
        String doc = createGetDoc("get");
        String funcBody = doc+
                "\n\t@RequestMapping(value = \"/get\", method = RequestMethod.GET)\n"+
                "\tpublic HttpResponse get(Integer id, BindingResult br){\n"+
                "\t\tif (id == null){\n" +
                "\t\t\tthrow new ArgumentsException(\"param.error.required\",\"id\");\n" +
                "\t\t}\n"+
                "\t\t"+modelCls.getClassName()+" "+Utils.lowerFistAlpha(modelCls.getClassName())+" = "+Utils.lowerFistAlpha(serviceCls.getClassName())+".get(id);\n"+
                "\t\tHttpResponse ret = HttpResponse.getSuccessResponse();\n"+
                "\t\tret.setData("+Utils.lowerFistAlpha(modelCls.getClassName())+");\n"+
                "\t\treturn ret;\n"+
                "\t}\n";
        return funcBody;
    }
    @Override
    public String createSearchFunc(){
        Ctx.MvcClass modelCls = getCtx().getMvcClass("model");
        Ctx.MvcClass searchCls = getCtx().getMvcClass("search");
        Ctx.MvcClass serviceCls = getCtx().getMvcClass("service");
        String varList = Utils.lowerFistAlpha(modelCls.getClassName())+"List";
        String doc = createGetDoc("search");
        String funcBody = doc +
                "\n\t@RequestMapping(value = \"/search\", method = RequestMethod.GET)\n"+
                "\tpublic HttpResponse search("+searchCls.getClassName()+" args, BindingResult br){\n"+
                "\t\tif (br.hasErrors()){\n" +
                "\t\t\tthrow new ArgumentsException(br.getFieldError().getDefaultMessage());\n" +
                "\t\t}\n"+
                "\t\tInteger totalCount = "+Utils.lowerFistAlpha(serviceCls.getClassName())+".getSearchCount(args);\n"+
                "\t\tListResult lr = new ListResult(totalCount, args.getOffset());\n"+
                "\t\tHttpResponse ret = HttpResponse.getSuccessResponse();\n"+
                "\t\tif(totalCount>0){\n"+
                "\t\t\tList<"+modelCls.getClassName()+"> data = "+Utils.lowerFistAlpha(serviceCls.getClassName())+".search(args);\n"+
                "\t\t\tlr.setItems(data);\n"+
                "\t\t}\n"+
                "\t\tret.setData(lr);\n"+
                "\t\treturn ret;\n"+
                "\t}\n";
        return funcBody;
    }

    @Override
    public String createJavaString(){
        Ctx.MvcClass cls = getMvcClass();

        Ctx.MvcClass modelCls = getCtx().getMvcClass("model");
        Ctx.MvcClass serviceCls = getCtx().getMvcClass("service");
        Ctx.MvcClass searchArgsCls = getCtx().getMvcClass("search");
        String pkgLine = "package "+cls.getPkg()+";\n\n";
        SortedSet importLines = new TreeSet();
        importLines.add("import java.util.List;");
        importLines.add("import "+ modelCls.getPkg()+"."+modelCls.getClassName()+";");
        importLines.add("import "+ searchArgsCls.getPkg()+"."+searchArgsCls.getClassName()+";");
        importLines.add("import "+ serviceCls.getPkg()+"."+serviceCls.getClassName()+";");
        importLines.add("import com.opener.common.http.HttpResponse;");
        importLines.add("import com.opener.web.spring.exception.ArgumentsException;");
        importLines.add("import com.opener.web.model.common.ListResult;");
        importLines.add("\n");
        importLines.add("import org.springframework.beans.factory.annotation.Autowired;");
        importLines.add("import org.springframework.web.bind.annotation.RequestMapping;");
        importLines.add("import org.springframework.web.bind.annotation.RestController;");
        importLines.add("import org.springframework.web.bind.annotation.RequestBody;");
        importLines.add("import org.springframework.web.bind.annotation.RequestMethod;");
        importLines.add("import org.springframework.validation.BindingResult;");

        StringBuffer classBody = new StringBuffer();
        classBody.append("@RestController\n");
        classBody.append("@RequestMapping(\"/api/v1/"+getMvcClass().getModName()+"\")\n");
        classBody.append("public class "+cls.getClassName()+"{\n");
        classBody.append("\t@Autowired\n");
        classBody.append("\tprivate "+serviceCls.getClassName()+" "+Utils.lowerFistAlpha(serviceCls.getClassName())+";\n\n");
        String insertFunc = createInsertFunc();
        String updateFunc = createUpdateFunc();
        String getFunc = createGetFunc();
        String searchFunc = createSearchFunc();
        String searchCountFunc = createSearchCountFunc();

        classBody.append(insertFunc);
        classBody.append(updateFunc);
        classBody.append(getFunc);
        classBody.append(searchFunc);

        classBody.append("}");
        String clsStr = pkgLine +
                StringUtils.collectionToDelimitedString(importLines,"\n") +"\n\n"+
                createClassDescString()+
                classBody.toString();
        return clsStr;
    }
}
